/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controller;

import com.google.gson.Gson;
import local.AttemptFacadeLocal;
import local.IndustryFacadeLocal;
import local.PublicUserFacadeLocal;
import local.QuestionFacadeLocal;
import local.ScoringFacadeLocal;
import local.ThemeFacadeLocal;
import local.ThemeScoreFacadeLocal;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.EJB;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import local.ComputeSessionLocal;
import local.ConfigurationFacadeLocal;
import local.RoleFacadeLocal;
import model.Attempt;
import model.Configuration;
import model.Industry;
import model.PublicUser;
import model.Question;
import model.Role;
import model.Scoring;
import model.Theme;
import model.ThemeScore;
import net.sf.jasperreports.engine.JasperRunManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import util.Email;
import util.JsonReturnDropDown;
import util.gv.GVServerPath;

/**
 *
 * @author Ken
 */
@WebServlet(name = "FrontEndServlet", urlPatterns = {"/FrontEndServlet"})
public class FrontEndServlet extends HttpServlet {

    Gson gson = new Gson();
    @EJB
    IndustryFacadeLocal industryFacade;
    @EJB
    ThemeFacadeLocal themeFacade;
    @EJB
    AttemptFacadeLocal attemptFacade;
    @EJB
    PublicUserFacadeLocal publicUserFacade;
    @EJB
    ScoringFacadeLocal scoringFacade;
    @EJB
    ThemeScoreFacadeLocal themeScoreFacade;
    @EJB
    QuestionFacadeLocal questionFacade;
    @EJB
    RoleFacadeLocal roleFacade;
    @EJB
    ConfigurationFacadeLocal configurationFacade;
    @EJB
    ComputeSessionLocal computeSession;
    private String json;

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String action = request.getParameter("action");

        if (action.equals("getReport") || action.equals("getPDF")) {
            try {
                if (action.equals("getReport")) {
                    getReport(request, response);
                } else {
                    getPDF(request, response);//for backend access
                }
            } catch (Exception ex) {
                //json = gson.toJson(new JsonReturnMsg("Error", ex.getMessage(), "error"));
                dispatchPage("/error.jsp", request, response);
                System.out.println(ex.getMessage());

            } finally {
                response.getOutputStream().close();
            }

        } else {
            try {
                if (action.equals("loadPage")) {
                    loadPage(request, response);

                } else if (action.equals("proceedToIndustryQns")) {
                    proceedToIndustryQns(request, response);
                    dispatchPage("/industryQns.jsp", request, response);

                } else if (action.equals("proceedToFirmQns")) {
                    proceedToFirmQns(request, response);
                    dispatchPage("/firmQns.jsp", request, response);

                } else if (action.equals("proceedToQns")) {
                    proceedToQns(request, response);
                    dispatchPage("/surveyQns.jsp", request, response);

                } else if (action.equals("proceedToEnd")) {
                    proceedToEnd(request, response);
                    //dispatchPage("/registration.jsp", request, response);

                } else if (action.equals("registration")) {
                    registration(request, response);
                    //dispatchPage("/registration.jsp", request, response);

                } else if (action.equals("retrieveReport")) {
                    retrieveReport(request, response);

                } else if (action.equals("checkEmail")) {
                    checkEmail(request, response);

                }

            } catch (Exception ex) {
                System.out.println(ex.getMessage());
                dispatchPage("/error.jsp", request, response);
            } finally {
                response.getWriter().close();
            }
        }
    }

    private void proceedToIndustryQns(HttpServletRequest request, HttpServletResponse response) throws Exception {
        long industry_id = Long.parseLong(request.getParameter("industries"));
        String country = request.getParameter("countries");

        PublicUser pu = new PublicUser();
        Attempt att = new Attempt();

        att.setCountry(country);
        att.setIndustry(industryFacade.find(industry_id));

        Role r = roleFacade.findRole("Public User");
        pu.setRole(r);

        HttpSession session = request.getSession();
        session.setAttribute("PublicUser", pu);
        session.setAttribute("Attempts", att);

        ArrayList<Theme> tList = new ArrayList(themeFacade.findThemeByIndustry(industry_id));

        Theme[] themes = new Theme[9];

        for (Theme t : tList) {

            switch (t.getPosition() - 1) {
                case 0:
                    themes[0] = t;
                    break;
                case 1:
                    themes[1] = t;
                    break;
                case 2:
                    themes[2] = t;
                    break;
                case 3:
                    themes[3] = t;
                    break;
                case 4:
                    themes[4] = t;
                    break;
                case 5:
                    themes[5] = t;
                    break;
                case 6:
                    themes[6] = t;
                    break;
                case 7:
                    themes[7] = t;
                    break;
                case 8:
                    themes[8] = t;
                    break;
                case 9:
                    themes[9] = t;
                    break;
            }
        }
        session.setAttribute("themeList", themes);
    }

    private void proceedToFirmQns(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String addr = request.getRemoteAddr();
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        Date date = new Date();
        String currentTimestamp = dateFormat.format(date);
        String tempNameEmail = addr + "@" + currentTimestamp;

        HttpSession session = request.getSession();
        PublicUser pu = new PublicUser();
        pu = (PublicUser) session.getAttribute("PublicUser");

        pu.setEmail(tempNameEmail);

        pu = publicUserFacade.create(pu);

        Attempt att = (Attempt) session.getAttribute("Attempts");
        att.setPu_id(pu.getPub_user_id());
        att.setIp_address(addr);
        att.setStatus(Attempt.SurveyStatus.Partial);
        att.setAck(Attempt.ReportLinkAcknowledge.No);
        att.setTimestamps(date);
        attemptFacade.create(att);
        att.setLink(att.getAttempt_id() + currentTimestamp);
        attemptFacade.edit(att);

        Theme[] themes = (Theme[]) session.getAttribute("themeList");

        for (int i = 0; i < themes.length; i++) {
            Theme th = (Theme) themes[i];
            int ans = Integer.parseInt(request.getParameter("indQns_" + th.getId()));
            ThemeScore ts = new ThemeScore();
            ts.setTheme_id(th.getId());
            ts.setInd_score(ans);
            ts.setTheme(th);
            themeScoreFacade.create(ts);
            att.getThemeScore().add(ts);
            attemptFacade.edit(att);
        }

        pu.getAttempt().add(att);
        publicUserFacade.edit(pu);

        session.setAttribute("themeList", themes);
        session.setAttribute("PublicUser", pu);
        session.setAttribute("Attempts", att);
    }

    private void proceedToQns(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpSession session = request.getSession();
        Theme[] themes = (Theme[]) session.getAttribute("themeList");

        Attempt att = (Attempt) session.getAttribute("Attempts");

        for (ThemeScore ts : att.getThemeScore()) {
            int ans = Integer.parseInt(request.getParameter("firmQns_" + ts.getTheme_id()));
            ts.setFirm_score(ans);
            themeScoreFacade.edit(ts);
        }

        Configuration config = configurationFacade.find(4);//Randomize survey question

        ArrayList<Question> qns = questionFacade.findQnsByThemes(themes, config);
        session.setAttribute("questionList", qns);
        session.setAttribute("Attempts", att);
        session.setAttribute("themeList", themes);
    }

    private void proceedToEnd(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpSession session = request.getSession();
        Attempt att = (Attempt) session.getAttribute("Attempts");

        ArrayList<Question> qns = (ArrayList<Question>) session.getAttribute("questionList");

        for (Question qn : qns) {
            int ans = Integer.parseInt(request.getParameter("qns_" + qn.getId()));
            Scoring sc = new Scoring();
            sc.setTheme_id(qn.getTheme_id());
            sc.setScore(ans);
            sc.setQuestion(qn);
            scoringFacade.create(sc);

            att.getScoring().add(sc);

            //check setting
            Configuration config = configurationFacade.find(5);//Randomize survey approval

            if (config.getStatus().equals(Configuration.ConfigurationStatus.True)) {
                att.setStatus(Attempt.SurveyStatus.Acceptable);

            } else {
                att.setStatus(Attempt.SurveyStatus.Completed);
            }

            attemptFacade.edit(att);
        }

        double[][] averageScores = computeSession.computeIndivFourFourSet(att);

        for (ThemeScore ts : att.getThemeScore()) {
            switch (((Theme) themeFacade.find(ts.getTheme_id())).getPosition()) {
                case 1:
                    ts.setAvg_score(averageScores[0][0]);
                    break;
                case 2:
                    ts.setAvg_score(averageScores[0][1]);
                    break;
                case 3:
                    ts.setAvg_score(averageScores[0][2]);
                    break;
                case 4:
                    ts.setAvg_score(averageScores[1][0]);
                    break;
                case 5:
                    ts.setAvg_score(averageScores[1][1]);
                    break;
                case 6:
                    ts.setAvg_score(averageScores[1][2]);
                    break;
                case 7:
                    ts.setAvg_score(averageScores[2][0]);
                    break;
                case 8:
                    ts.setAvg_score(averageScores[2][1]);
                    break;
                case 9:
                    ts.setAvg_score(averageScores[2][2]);
                    break;
            }
            themeScoreFacade.edit(ts);
        }

        //setting
        Configuration config = configurationFacade.find(1);//Registration needed to view report

        if (config.getStatus() == Configuration.ConfigurationStatus.True) {
            session.setAttribute("regFlag", "true");

        } else {
            session.setAttribute("regFlag", "false");
        }

        //call zy code
        boolean configBench =false;
        Configuration config2 = configurationFacade.find(2);//benchmark in report

        if (config2.getStatus() == Configuration.ConfigurationStatus.True) {
            configBench=true;

        } else {
            configBench=false;
        }
        
        boolean configRec =false;
        Configuration config3 = configurationFacade.find(3);//Recommendation included in report

        if (config3.getStatus() == Configuration.ConfigurationStatus.True) {
            configRec=true;

        } else {
            configRec=false;
        }
        
        
        
        ArrayList dataList = computeSession.prepareReportGraph(computeSession.superComputeOne(att), att.getIndustry().getId(), configBench,configRec);
        //

        byte[] pdf = produceReport(request, response, dataList);
        att.setPdfStream(pdf);
        attemptFacade.edit(att);

        session.setAttribute("Attempts", att);
        json = gson.toJson("success");
        response.getWriter().println(json);
    }

    private byte[] produceReport(HttpServletRequest request, HttpServletResponse response, ArrayList dataList) throws Exception {
        byte[] pdf = null;
        HttpSession session = request.getSession();

        //report para
        Map parameters = new HashMap();
        // ChartsHelper ch = (ChartsHelper) dataList.get(dataList.size() - 1);
        parameters.put("title", "");
        
        //set to domain
        //"/opt/glassfishv3/glassfish/domains/domain1/";//for server
        parameters.put("subDir", GVServerPath.ServerPath);
        Attempt att = (Attempt) session.getAttribute("Attempts");

        SimpleDateFormat formatter;
        formatter = new SimpleDateFormat("dd/MM/yyyy");
        parameters.put("desc", formatter.format(att.getTimestamps()));

        Configuration config = configurationFacade.find(2);//Registration needed to view report

        if (config.getStatus() == Configuration.ConfigurationStatus.True) {
            parameters.put("benchmarkFlag", true);

        } else {
            parameters.put("benchmarkFlag", false);
        }

        // streams
        String reportPath = "/jasperreports/report_v1.jasper";

        InputStream reportStream = request.getServletContext().getResourceAsStream(reportPath);

        pdf = JasperRunManager.runReportToPdf(reportStream, parameters, new JRBeanCollectionDataSource(dataList));
        
        return pdf;
    }

    private void registration(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpSession session = request.getSession();
        String email = (String) request.getParameter("email");
        String name = (String) request.getParameter("name");
        String company_name = (String) request.getParameter("company_name");
        String title = (String) request.getParameter("title");
        String company_size = (String) request.getParameter("company_size");
        String it_size = (String) (request.getParameter("it_size"));

        PublicUser pu = (PublicUser) session.getAttribute("PublicUser");
        Attempt att = (Attempt) session.getAttribute("Attempts");
        att.setCompany_name(company_name);
        att.setTitle(title);
        att.setCompany_size(company_size);
        att.setIt_dept_size(it_size);
        attemptFacade.edit(att);

        Role r = roleFacade.findRole("Registered User");
        pu.setRole(r);
        pu.setName(name);

        publicUserFacade.registration(email, pu);

        json = gson.toJson("success");

        if (!email.isEmpty()) {
            Email emailManager = new Email();

//            String pathLink = request.getLocalName()
//                    + ":"
//                    + request.getLocalPort()
//                    + request.getRequestURI();
            
            String pathLink= GVServerPath.ServeletUrl;
            pu = publicUserFacade.getPublicUser(email);

            boolean emailStatus = emailManager.emailNewReportLink(email, pu, pathLink, att);
            if (emailStatus == false) {
                json = gson.toJson("email-failed");
            }
        }

        response.getWriter().println(json);
    }

    private void retrieveReport(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String email = (String) request.getParameter("email");
        String email0 = (String) request.getParameter("email0");
        String ret = publicUserFacade.retrieveReport(email);
        json = "success";
        if (email.equals(email0)) {
            if (ret.equals("success")) {
                json = gson.toJson("success");
                PublicUser pu = publicUserFacade.getPublicUser(email);
                Email emailManager = new Email();
                String pathLink= GVServerPath.ServeletUrl;
//                String pathLink = request.getLocalName()
//                        + ":"
//                        + request.getLocalPort()
//                        + request.getRequestURI();

                boolean emailStatus = emailManager.emailReportLinks(email, pu, pathLink);
                if (emailStatus == false) {
                    json = gson.toJson("email-failed");
                }
            } else {
                json = gson.toJson("fail");
            }
        } else {
            json = gson.toJson("fail");
        }
        response.getWriter().println(json);
    }

    private void getReport(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String link = (String) request.getParameter("getPDF");
        Attempt att = attemptFacade.getAttemptByLink(link);
        byte[] pdf = att.getPdfStream();

        att.setAck(Attempt.ReportLinkAcknowledge.Yes);
        attemptFacade.edit(att);

        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "inline; filename=" + att.getTimestamps() + ".pdf");
        response.setHeader("Cache-Control", "cache, must-revalidate");
        response.setHeader("Pragma", "public");
        response.getOutputStream().write(pdf);
    }
    
    private void getPDF(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String attempt_id = request.getParameter("attempt_id");
        Attempt att = attemptFacade.getAttempt(Long.parseLong(attempt_id));
        byte[] pdf = att.getPdfStream();

        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "inline; filename=" + att.getTimestamps() + ".pdf");
        response.setHeader("Cache-Control", "cache, must-revalidate");
        response.setHeader("Pragma", "public");
        response.getOutputStream().write(pdf);
    }

    private void checkEmail(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String email = (String) request.getParameter("email");
        String ret = publicUserFacade.checkEmail(email);
        json = "success";
        if (ret.equals("success")) {
            json = gson.toJson("success");

        } else {
            json = gson.toJson("fail");
        }

        response.getWriter().println(json);
    }

    //ui
    private void loadPage(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String content = request.getParameter("content");

        if (content.equals("getIndustries")) {
            ArrayList<Industry> dList = new ArrayList<Industry>(industryFacade.findAll());
            ArrayList<JsonReturnDropDown> iList = new ArrayList();

            JsonReturnDropDown dd0 = new JsonReturnDropDown();
            dd0.setId(0);
            dd0.setText("");
            iList.add(dd0);
            for (Industry i : dList) {
                JsonReturnDropDown dd = new JsonReturnDropDown();
                dd.setId(Integer.parseInt(i.getId() + ""));
                dd.setText(i.getName());
                iList.add(dd);
            }
            json = gson.toJson(iList);
            response.getWriter().println(json);
        }
    }

    //util
    private void dispatchPage(String page, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            RequestDispatcher dispatcher;
            ServletContext servletContext = getServletContext();
            dispatcher = servletContext.getRequestDispatcher(page);
            if (dispatcher == null) {
                dispatcher = servletContext.getRequestDispatcher("error");
            }

            dispatcher.forward(request, response);

        } catch (Exception ex) {
            System.out.println(ex);
        }
    }
    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">

    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
